package com.homedo.async.mysql.support.mapper.select;

import com.homedo.async.common.dto.Pagination;
import com.homedo.async.mysql.support.dataobject.Example;
import com.homedo.async.mysql.support.dml.DMLEnum;
import com.homedo.async.mysql.support.mapper.util.CreateFlux4RecordResultUtil;
import com.homedo.async.mysql.support.meta.EntityMetaData;
import com.homedo.async.mysql.support.prepare.PrepareObject2Sql;
import com.homedo.async.mysql.support.prepare.PrepareObjectType;
import com.homedo.plainly.logger.Logger;
import com.homedo.plainly.logger.LoggerFactory;
import io.vertx.sqlclient.Pool;
import io.vertx.sqlclient.SqlConnection;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;

/**
 * @author jgshun
 * @date 2020/3/17 10:41 AM
 */
public class SelectMapperExampleImpl<T, ID> implements SelectMapperExampleI<T, ID> {
    private static final Logger _LOGGER = LoggerFactory.getLogger(SelectMapperExampleImpl.class);

    private Pool pool;

    private EntityMetaData<T> entityMetaData;

    public SelectMapperExampleImpl(Pool pool, EntityMetaData<T> entityMetaData) {
        this.pool = pool;
        this.entityMetaData = entityMetaData;
    }


    @Override
    public Flux<T> findByExample(Example example) {
        return this.findByExample(example, (SqlConnection) null);
    }

    @Override
    public Flux<T> findByExample(Example example, SqlConnection connection) {
        Assert.notNull(example, "The given example must not be null!");

        Object[] prepareSqlArgs = new PrepareObject2Sql(example, entityMetaData, DMLEnum.SELECT, PrepareObjectType.ENTITY_EXAMPLE, false).prepare();

        return this.createSelectFlux(prepareSqlArgs, connection);
    }

    @Override
    public Flux<T> findByExample(Example example, Pagination<T> pagination) {
        return this.findByExample(example, pagination, null);
    }

    @Override
    public Flux<T> findByExample(Example example, Pagination<T> pagination, SqlConnection connection) {
        Assert.notNull(example, "The given example must not be null!");

        PrepareObject2Sql prepareObject2Sql = new PrepareObject2Sql(example, entityMetaData, DMLEnum.SELECT, PrepareObjectType.ENTITY_EXAMPLE, false);
        prepareObject2Sql.setPagination(pagination);

        Object[] prepareSqlArgs = prepareObject2Sql.prepare();

        return this.createSelectFlux(prepareSqlArgs, connection);
    }

    private Flux<T> createSelectFlux(Object[] prepareSqlArgs, SqlConnection connection) {
        return CreateFlux4RecordResultUtil.create(prepareSqlArgs, this.pool, this.entityMetaData.getCollector(), connection);
    }


}
